<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="hyi8c" id="hyi8c"><span data-lake-id="u22534742" id="u22534742">典型回答</span></h1>
  <p data-lake-id="ud2ce83f0" id="ud2ce83f0"><br></p>
  <p data-lake-id="u607de22f" id="u607de22f"><strong><span data-lake-id="ua1fc8f4f" id="ua1fc8f4f" class="lake-fontsize-11" style="color: rgb(36, 41, 46)">Nacos 2.X 在 1.X 的架构基础上，通信层通过 gRPC 和 Rsocket 实现了长连</span></strong><strong><span data-lake-id="u2a457712" id="u2a457712">接 RPC 调用和推送能力。主要是为了改善Nacos在大规模集群环境下的性能和稳定性。</span></strong></p>
  <p data-lake-id="u4cc6fa45" id="u4cc6fa45"><span data-lake-id="u2284c21c" id="u2284c21c" class="lake-fontsize-11" style="color: rgb(36, 41, 46)">​</span><br></p>
  <blockquote data-lake-id="u5c9b84b4" id="u5c9b84b4">
   <p data-lake-id="u370bacb5" id="u370bacb5"><span data-lake-id="ub880e9c9" id="ub880e9c9">同时新增一个链接层，用来将不同类型的 Request 请求，将来自不同客户端的不同类型请求，转化为相同语意的功能数据结构，复用业务处理逻辑。同时，将来的流量控制和负载均衡等功能也会在链接层处理。</span></p>
  </blockquote>
  <p data-lake-id="u7999a362" id="u7999a362"><br></p>
  <p data-lake-id="u4c2e5623" id="u4c2e5623"><span data-lake-id="u8d377578" id="u8d377578"><br></span><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1688463935239-bb06659a-8217-4ec5-ab22-e2001053409a.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_47%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u553a28ae" id="u553a28ae"><br></p>
  <p data-lake-id="u1809d37f" id="u1809d37f"><span data-lake-id="u0a399aa4" id="u0a399aa4">在Nacos的早期版本中，节点之间的通信采用了HTTP协议。在高并发、大规模集群环境下，由于HTTP的连接管理和请求响应的开销，会导致一些性能和稳定性方面的问题。</span></p>
  <p data-lake-id="u3320663c" id="u3320663c"><span data-lake-id="u8f4b3aa3" id="u8f4b3aa3">​</span><br></p>
  <p data-lake-id="u60cd5265" id="u60cd5265"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1688464018606-9559cfb2-b8b8-4f1a-9cfe-c8a50a204867.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_50%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ubfd93192" id="ubfd93192"><br></p>
  <p data-lake-id="uf022f39d" id="uf022f39d"><span data-lake-id="u3b0d3d06" id="u3b0d3d06">HTTP 短连接模型，每次客户端请求都会创建和销毁 TCP 链接，TCP 协议销毁的链接状态是 WAIT_TIME，完全释放还需要一定时间，当 TPS 和 QPS 较高时，服务端和客户端可能有大量的 WAIT_TIME 状态链接，从而会导致 connect time out 错误或者 Cannot assign requested address 的问题。</span></p>
  <p data-lake-id="u7d7aa5b5" id="u7d7aa5b5"><span data-lake-id="u992b250b" id="u992b250b">​</span><br></p>
  <p data-lake-id="u5e89f70b" id="u5e89f70b"><span data-lake-id="u6e02eef4" id="u6e02eef4">配置模块使用 HTTP 短连接阻塞模型来模拟长连接通信，但是由于并非真实的长连接模型，因此每 30 秒需要进行一次请求和数据的上下文切换，每一次切换都有引起造成一次内存浪费，从而导致服务端频繁 GC。</span></p>
  <p data-lake-id="u1affb3c7" id="u1affb3c7"><span data-lake-id="u60759f62" id="u60759f62">​</span><br></p>
  <p data-lake-id="u4f644c61" id="u4f644c61"><span data-lake-id="u86ab1a9e" id="u86ab1a9e">在大规模集群环境下，维护大量的HTTP连接会给负载均衡、路由等方面的管理带来一定的复杂性。并且HTTP协议对请求和响应的内容通常需要进行压缩和序列化处理，这也会带来一定的开销。</span></p>
  <p data-lake-id="ud417eb17" id="ud417eb17"><span data-lake-id="u1453b27c" id="u1453b27c">​</span><br></p>
  <p data-lake-id="ub01a5eed" id="ub01a5eed"><span data-lake-id="u35ecadca" id="u35ecadca">同时，1.0的版本中还存在以下几个问题：</span></p>
  <p data-lake-id="uad1d8e7d" id="uad1d8e7d"><span data-lake-id="ubfad7249" id="ubfad7249">​</span><br></p>
  <p data-lake-id="u08f59333" id="u08f59333"><span data-lake-id="uaa835066" id="uaa835066">通过心跳续约，当服务规模上升时，特别是类似 Dubbo 的接口级服务较多时，心跳及配置元数据的轮询数量众多，导致集群 TPS 很高，系统资源高度空耗。</span></p>
  <p data-lake-id="u6fa2ac69" id="u6fa2ac69"><span data-lake-id="uec77ddb2" id="uec77ddb2">​</span><br></p>
  <p data-lake-id="u0c586579" id="u0c586579"><span data-lake-id="u7a8344d0" id="u7a8344d0">心跳续约需要达到超时时间才会移除并通知订阅者，默认为 15s，时延较长，时效性差。若改短超时时间，当网络抖动时，会频繁触发变更推送，对客户端服务端都有更大损耗。</span></p>
  <p data-lake-id="u04cec0ff" id="u04cec0ff"><span data-lake-id="uf2562264" id="uf2562264">​</span><br></p>
  <p data-lake-id="u3b1f24c1" id="u3b1f24c1"><span data-lake-id="u378404ea" id="u378404ea">为了解决这些问题，Nacos 2.x引入了gRPC的通信方式</span></p>
  <p data-lake-id="ub3e3ff0a" id="ub3e3ff0a"><span data-lake-id="uf0590a85" id="uf0590a85">​</span><br></p>
  <p data-lake-id="u21727c28" id="u21727c28"><span data-lake-id="u3df072d8" id="u3df072d8">Nacos2架构下的服务发现，客户端通过gRPC，发起注册服务或订阅服务的请求。服务端使用Client对象来记录该客户端使用gRPC连接发布了哪些服务，又订阅了哪些服务，并将该Client进行服务间同步。由于实际的使用习惯是服务到客户端的映射，即服务下有哪些客户端实例。</span></p>
  <p data-lake-id="uec801dff" id="uec801dff"><span data-lake-id="u67a50de8" id="u67a50de8"><br></span><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1688464160204-4ab46daa-eef1-4454-9e65-1f490e888bb5.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_46%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u2cb3dd9b" id="u2cb3dd9b"><br></p>
  <p data-lake-id="u36d4e370" id="u36d4e370"><span data-lake-id="u1cb4743a" id="u1cb4743a">配置管理之前用Http1.1的Keep Alive模式30s发一个心跳模拟长链接，协议难以理解，内存消耗大，推送性能弱，因此2.0通过gRPC彻底解决这些问题，内存消耗大量降低。</span></p>
  <p data-lake-id="ud2c57f6b" id="ud2c57f6b"><span data-lake-id="u7d95950f" id="u7d95950f">​</span><br></p>
  <p data-lake-id="uc0b17411" id="uc0b17411"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1688464408682-715d06d3-aa7d-474b-91b4-7878ceda245d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ued88296b" id="ued88296b"><span data-lake-id="u1fe1b14f" id="u1fe1b14f">​</span><br></p>
  <p data-lake-id="ube83f3b3" id="ube83f3b3"><br></p>
  <ul list="u8de93d64">
   <li fid="uc9c43687" data-lake-id="u50e05bed" id="u50e05bed"><span data-lake-id="u98cf9ffb" id="u98cf9ffb">客户端不再需要定时发送实例心跳，只需要有一个维持连接可用 keepalive 消息即可。重复 TPS 可以大幅降低。</span></li>
   <li fid="uc9c43687" data-lake-id="u45284e2c" id="u45284e2c"><span data-lake-id="u5f5692ed" id="u5f5692ed">TCP 连接断开可以被快速感知到，提升反应速度。</span></li>
   <li fid="uc9c43687" data-lake-id="u9ec51741" id="u9ec51741"><span data-lake-id="u19521f6f" id="u19521f6f">长连接避免频繁连接开销，可以大幅缓解 TIME_ WAIT 问题。</span></li>
   <li fid="uc9c43687" data-lake-id="u39d0bb5f" id="u39d0bb5f"><span data-lake-id="u00736738" id="u00736738">真实的长连接，解决配置模块 GC 问题。</span></li>
   <li fid="uc9c43687" data-lake-id="u1d6cb655" id="u1d6cb655"><span data-lake-id="u3cbbe64b" id="u3cbbe64b">更细粒度的同步内容，减少服务节点间的通信压力。</span></li>
  </ul>
  <p data-lake-id="u299d39c0" id="u299d39c0"><span data-lake-id="u13d7b467" id="u13d7b467">​</span><br></p>
  <p data-lake-id="u5296bed1" id="u5296bed1"><span data-lake-id="ueba0e23e" id="ueba0e23e">当然，缺点也是存在的。那就是RPC 协议的观测性不如 HTTP。即使 gRPC 基于 HTTP2.0 Stream 实现，仍然不如直接使用 HTTP 协议来的直观。</span></p>
 </body>
</html>